type EventCallback = Function & { once?: boolean };

class EventCenter {

    private static map = new Map<string, Set<EventCallback>>()

    static on(eventName: string, fn: EventCallback) {
        const eventSet: Set<EventCallback> = this.map.get(eventName) ?? new Set();
        eventSet.add(fn);
        this.map.set(eventName, eventSet);
    }

    static off(eventName: string, fn?: EventCallback) {
        const eventSet: Set<EventCallback> = this.map.get(eventName) ?? new Set();
        if (fn) {
            eventSet.delete(fn);
        } else {
            eventSet.clear();
        }
    }

    static emit(eventName: string, ...args: any[]) {
        const eventSet: Set<EventCallback> = this.map.get(eventName) ?? new Set();
        eventSet.forEach(function (fn: EventCallback) {
            if (fn instanceof Function) {
                fn(...args);
                fn.once && Promise.resolve().then(() => eventSet.delete(fn))
            }
        })
    }

    static once(eventName: string, fn: EventCallback) {
        const eventSet: Set<EventCallback> = this.map.get(eventName) ?? new Set();
        fn.once = true;
        eventSet.add(fn);
        this.map.set(eventName, eventSet);
    }
}

function go() {
    console.log('go')
}

function go1() {
    console.log('go 1')
}

EventCenter.on('go', go)

EventCenter.once('go', go1)

setTimeout(() => {
    EventCenter.emit('go');
}, 1000);



setTimeout(() => {
    EventCenter.emit('go');
}, 2000);

setTimeout(() => {
    EventCenter.off('go', go);
}, 2500);

setTimeout(() => {
    EventCenter.emit('go');
}, 3000);